-
Notifications
You must be signed in to change notification settings - Fork 7
feat(omnium): Add caplet vat implementation #753
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
451a6dd to
605f8d9
Compare
6736065 to
89e5113
Compare
605f8d9 to
f08383c
Compare
f08383c to
34a1f08
Compare
89e5113 to
ee93a06
Compare
34a1f08 to
4caf528
Compare
Answers @kumavis's challenge of "What're you afraid of CapTP or something?" by replacing our kernel JSON-RPC API with `E()` on a facet of the kernel. This makes it easy to expose as much of the kernel API as we want via eventual send, and allows us to benefit from pipelining internally. In addition, it facilitates the removal of the command stream and the related RPC API logic. Finally, a number of rationalizations are applied to the extension and omnium. This PR is part of a stack followed by: #752, #753, and #754 <!-- CURSOR_SUMMARY --> --- > [!NOTE] > Introduces CapTP-based communication and removes the JSON-RPC command stream. > > - Add CapTP utilities in `kernel-browser-runtime`: `makeBackgroundCapTP`, `makeKernelCapTP`, `makeKernelFacade`, and JSON-RPC `captp` notification helpers; export new `KernelFacade` and `CapTPMessage` types > - Update `kernel-worker` to use CapTP for background↔kernel messaging; initialize kernel without a command stream; route internal RPC only for panel/internal comms > - Refactor `@MetaMask/ocap-kernel` to drop command stream handling and kernel RPC entrypoints; `Kernel.make` now accepts only platform services and the database; adjust `stop()` accordingly > - Migrate extension and omnium backgrounds/offscreens to CapTP over `ChromeRuntimeDuplexStream`, use global `E` and `kernel`/`omnium` helpers; remove `env/dev-console` and background trusted prelude files; add TS globals > - Add unit and integration tests for CapTP (`background-captp`, kernel-side CapTP, and E() end-to-end); introduce `vitest.integration.config.ts` and `test:integration` scripts; CI gains an "Integration Tests" job > - Update deps (add `@endo/captp`, `@endo/eventual-send`), tsconfigs, build constants, and minor coverage thresholds > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit cbf22fd. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY --> --------- Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
d014ffd to
1ab49c9
Compare
9ab3158 to
84ed1b2
Compare
Introduces "controllers" to Omnium. A controller is an object (class) responsible for a slice of application state. We inherit this nomenclature from MetaMask. In detail: - Add modular controller architecture with POLA attenuation via `makeFacet()` - `makeFacet()` is tentative, and may be removed later in the stack in favor of just public and private methods. - Add `ControllerStorage` abstraction with `immer`-based state management and debounced persistence - Add platform storage adapters and Chrome-specific implementation - Add `Controller` abstract base class - Add `CapletController` for managing installed caplets **Part 2 of 4 in PR stack** Depends on: #751 Followed by: #753 <!-- CURSOR_SUMMARY --> --- > [!NOTE] > Introduces a modular controller layer and integrates it into the extension background, enabling managed, persisted state and caplet lifecycle operations. > > - **Controller framework:** Adds abstract `Controller`, `ControllerStorage` (immer-based with debounced, per-key persistence), and a Chrome storage adapter > - **Caplet management:** New `CapletController` with `install/uninstall/list/get`, manifest validation, and kernel subcluster launch/terminate via `initializeControllers` > - **Background integration:** Refactors globals to `omnium` (`E`, `getKernel`, `ping`) and exposes `omnium.caplet` methods; adds error propagation to offscreen stream > - **Types/utilities:** Exports `Promisified` type; caplet types/guards with superstruct and semver > - **Config/tests:** Adds deps (exo, superstruct, immer, semver), grants `storage` permission in manifest, and comprehensive unit/e2e tests > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 0e330b6. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY --> --------- Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
84ed1b2 to
675ff3e
Compare
Coverage Report
File Coverage |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cursor Bugbot has reviewed your changes and found 3 potential issues.
packages/kernel-browser-runtime/src/kernel-worker/captp/kernel-facade.ts
Show resolved
Hide resolved
| // Return wrapped kref for future CapTP marshalling to presence | ||
| // TODO: Enable custom CapTP marshalling tables to convert this to a presence | ||
| return { kref: krefString }; | ||
| }, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As Bugbot so astutely points out, this doesn't work, and won't work until #754.
Implements Phase 1a of the caplet system, establishing the foundational architecture for caplet vats with a working echo-caplet example. This validates the caplet vat contract and installation lifecycle before tackling service injection complexity. Changes: - Add comprehensive caplet vat contract documentation - Create echo-caplet.js demonstrating buildRootObject pattern - Add bundle build script using @endo/bundle-source - Implement caplet integration tests (8 new tests, all passing) - Create test fixtures for caplet manifests - Refactor makeMockStorageAdapter to support shared storage - Add plan in .claude/plans for follow-up work Key achievements: - Caplet vat contract fully documented with examples - Echo-caplet bundles successfully (696KB) - Install/uninstall lifecycle tested and working - Service lookup by name validated - State persistence across controller restarts verified - 100% code coverage for CapletController maintained Deferred to future work (Phase 1b): - Kref capture mechanism - Service parameter injection - Consumer caplet implementation - Two-caplet communication Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Implements Phase 1b functionality to store caplet root kernel references (krefs) and expose them via omnium.caplet.getCapletRoot(). This enables: omnium.caplet.install(manifest), omnium.caplet.getCapletRoot(capletId), and E(presence).method() for calling vat methods from background console. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add explicit type annotation for kernelP and use spread operator for optional rootKref field. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Remove KrefWrapper type from kernel-browser-runtime types - Make rootKref a required string field in LaunchResult (not optional) - Make rootKref required in InstalledCaplet and omnium LaunchResult - Add assertions in kernel-facade for capData, subclusterId, and rootKref - Remove isKrefWrapper function (inline check kept in makeKrefTables) - Update tests to use simplified types and improved mocks Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add tests for validation errors in kernel-facade launchSubcluster: - Throws when kernel returns no capData - Throws when capData body has no subclusterId - Throws when capData slots is empty (no root kref) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add omnium.manifests.echo so users can install caplets from the console: await omnium.caplet.install(omnium.manifests.echo) Changes: - Create src/manifests.ts with echo caplet manifest using chrome.runtime.getURL - Add echo-caplet.bundle to vite static copy targets - Expose manifests in background.ts via omnium.manifests - Update global.d.ts with manifests type and missing getCapletRoot Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add omnium.loadCaplet(id) to dynamically fetch caplet manifest and bundle - Fix vatPowers.logger missing in browser vats (iframe.ts) - Fix SubclusterLaunchResult to return bootstrapRootKref directly instead of trying to extract it from bootstrap() return slots The bootstrapRootKref is the kref of the vat root object, which is already known when the vat launches. Previously we incorrectly tried to get it from the slots of the bootstrap() method return value. Next step: Wire up CapTP marshalling so E(root).echo() works with the caplet root presence. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Use nullable() instead of optional() for bootstrapResult field, and define a JSON-compatible LaunchSubclusterRpcResult type that uses null instead of undefined for JSON serialization. Also update tests to match the new behavior. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add comprehensive unit test coverage for the getCapletRoot method: - Test successful retrieval of caplet root and getVatRoot call verification - Test error case when caplet not found - Test error case when caplet has no root object (empty rootKref) Co-Authored-By: Claude <noreply@anthropic.com>
Move caplet source, bundle, and manifest to a single directory structure (src/caplets/echo/) to keep related files together. Add bundleSpec to the manifest so it's complete. Simplify loadCaplet() and test fixtures by having them resolve bundleSpec at runtime. Changes: - Move src/vats/echo-caplet.js → src/caplets/echo/echo-caplet.js - Move src/caplets/echo.manifest.json → src/caplets/echo/manifest.json - Add bundleSpec: "echo-caplet.bundle" to manifest - Update build:vats script to build:caplets targeting src/caplets/echo - Simplify vite.config.ts static copy targets (no more rename logic) - Update loadCaplet() to fetch manifest from caplet subdirectory - Update test fixtures to import real manifest and override bundleSpec - Fix global.d.ts to correctly type omnium.caplet.load - Add caplets/*.js to eslint exemptions (like vats/*.js) Co-Authored-By: Claude <noreply@anthropic.com>
Remove vatPowers logger parameter from echo-caplet since console.log is sufficient for logging. This also reverts the vatPowers provision in iframe.ts that was only added to support this. Co-Authored-By: Claude <noreply@anthropic.com>
e0d8b07 to
bc6e395
Compare
FUDCo
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Surprisingly straightforward.
Adds an actual caplet implementation, the echo caplet, and enables installing it and retrieving a reference to its root object from the extension's background console. The returned object is not actually a usable presence, but we implement this in #754.
In detail:
launchSubcluster()omnium.caplet.load()for dynamic caplet loadingPart 3 of 4 in PR stack
Depends on: #752
Followed by: #754
Note
Introduces caplet plumbing and updates kernel launch semantics to return identifiers needed to reference caplet roots.
launchSubcluster()now returnsSubclusterLaunchResult{ subclusterId, bootstrapRootKref, bootstrapResult };SubclusterManagerandKernelupdated; types exportedlaunchSubclusternow returns{ subclusterId, rootKref }; addedgetVatRoot(krefString); CapTP/RPC handler/spec updated to return structured result and normalizebootstrapResultundefined→nullomnium.caplet.load(); CapletController now storesrootKref, supportsgetCapletRoot(), and uses kernel facadelaunchSubcluster/getVatRoot; integration tests addedsrc/**/caplets; build script bundles capletsWritten by Cursor Bugbot for commit bc6e395. This will update automatically on new commits. Configure here.